package com.qubyer.widget.adapter

import android.view.ViewGroup
import androidx.databinding.ViewDataBinding

abstract class HeaderBindingRvAdapter<T, DB : ViewDataBinding>(dataList: ArrayList<T> = ArrayList()) : BindingRvAdapter<T, ViewDataBinding>(dataList) {

    companion object {
        const val HEADER_ITEM_TYPE = -1000
    }

    private val headers = ArrayList<IHeader>()

    fun addHeader(header: IHeader) {
        if (!headers.contains(header)) {
            headers.add(header)
        }
    }

    override fun addDataList(data: List<T>?) {
        if (data != null) {
            val previousSize = dataList.size
            dataList.addAll(data)
            notifyItemRangeInserted(previousSize + headers.size, data.size)
        }
    }

    override fun addData(data: T) {
        dataList.add(data)
        notifyItemInserted(dataList.size - 1 + headers.size)
    }

    override fun replaceData(index: Int, data: T) {
        dataList[index] = data
        notifyItemChanged(index + headers.size)
    }

    override fun remove(data: T) {
        val index = dataList.indexOf(data)
        if (index >= 0) {
            dataList.removeAt(index)
            notifyItemRemoved(index + headers.size)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder<ViewDataBinding> {
        if (isHeaderViewType(viewType)) {
            return BindingViewHolder(headers[HEADER_ITEM_TYPE - viewType].getViewDataBinding())
        }
        return super.onCreateViewHolder(parent, viewType)
    }

    override fun onBindViewHolder(holder: BindingViewHolder<ViewDataBinding>, position: Int) {
        if (!isHeader(position)) {
            onRealBind(getItem(position - headers.size), holder.dataBinding as DB)
        }
    }

    override fun onBind(data: T, dataBinding: ViewDataBinding) {
        //Nothing to do
    }

    abstract fun onRealBind(data: T, dataBinding: DB)

    override fun getItemViewType(position: Int): Int {
        if (isHeader(position)) {
            return HEADER_ITEM_TYPE - position
        }
        return super.getItemViewType(position)
    }

    fun isHeader(position: Int): Boolean {
        return position < headers.size
    }

    private fun isHeaderViewType(viewType: Int): Boolean {
        return viewType <= HEADER_ITEM_TYPE
    }

    override fun getItemCount(): Int {
        return dataList.size + headers.size
    }

    override fun setDataList(list: List<T>?) {
        val previousSize = dataList.size
        dataList.clear()
        notifyItemRangeRemoved(headers.size, previousSize)
        if (list != null) {
            dataList.addAll(list)
            notifyItemRangeInserted(headers.size, dataList.size)
        }
    }
}